/**
 * 
 */
package cn.hg.solon.youcan.framework.web.admin.filter;

import java.util.Date;

import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.JSONUtil;
import org.noear.solon.core.event.EventBus;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Result;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hg.solon.youcan.common.enums.BusinessStatus;
import cn.hg.solon.youcan.framework.satoken.SaUtil;
import cn.hg.solon.youcan.framework.web.admin.annotation.Logging;
import cn.hg.solon.youcan.system.entity.Dept;
import cn.hg.solon.youcan.system.entity.OperateLog;
import cn.hg.solon.youcan.system.entity.User;

/**
 * @author 胡高
 *
 */
public class OperateLogReporter {

    public static void logging(Context ctx, Logging log, Date start, Date end) {
        if (ObjUtil.isNull(ctx)) {
            return;
        }
        OperateLog operateLog = createLog(ctx, log, start, end, ctx.errors);
        setOperator(operateLog);
        EventBus.publishAsync(operateLog);
    }

    private static OperateLog createLog(Context ctx, Logging log, Date start, Date end, Throwable e) {
        // 创建日志记录
        OperateLog logAction = new OperateLog();

        logAction.setActionDatetime(start);
        logAction.setCost((int)(end.getTime() - start.getTime()));
        logAction.setIp(ctx.realIp());
        if (ObjUtil.isNotNull(ctx.controller())) {
            logAction.setMethod(ctx.controller().getClass().getName() + "." + ctx.action().name());
        }
        if (log.isSaveRequestData()) {
            // 保存请求的参数
            logAction.setParam(JSONUtil.toJsonStr(ctx.paramMap()));
        }
        logAction.setRequestMethod(ctx.method());
        logAction.setTitle(log.title());
        logAction.setType(log.businessType().name());
        logAction.setUrl(ctx.pathNew());

        setResult(logAction, log, ctx, e);

        return logAction;
    }

    private static void setOperator(OperateLog operateLog) {
        try {
            SaSession session = StpUtil.getTokenSession();
            if (ObjUtil.isNull(session)) {
                return;
            }

            User user = SaUtil.getCurrentUser();
            if (ObjUtil.isNotNull(user)) {
                operateLog.setUserId(user.getId());
                operateLog.setUserName(user.getNickname());
            }

            Dept dept = SaUtil.getCurrentDept();
            if (ObjUtil.isNotNull(dept)) {
                operateLog.setDeptId(dept.getId());
                operateLog.setDeptName(dept.getName());
            }
        } catch (Throwable e) {
            return;
        }
    }

    private static void setResult(OperateLog logAction, Logging log, Context ctx, Throwable e) {
        if (ObjUtil.isNotNull(e)) {
            logAction.setMessage(e.getMessage());
            logAction.setStatus(BusinessStatus.FAILED.name());
            return;
        }
        Object result = ctx.result;
        if (ObjUtil.isNull(result)) {
            logAction.setStatus(BusinessStatus.SUCCESSED.name());
        } else {
            if (result instanceof Result) {
                Result<?> ret = (Result<?>)result;
                logAction.setStatus(
                    ret.getCode() == Result.SUCCEED_CODE ? BusinessStatus.SUCCESSED.name() : BusinessStatus.FAILED.name());
                logAction.setMessage(ret.getDescription());
            }
            if (log.isSaveResponseData()) {
                // 保存响应的参数
                logAction.setResult(JSONUtil.toJsonStr(result));
            }
        }
    }

}
